<?php
namespace PsiFramework\Classes\Util\Manager;

import("Classes.Util.Application");
import("Classes.Util.HTTP.Request");
import("Classes.Util.HTTP.Session");
import("Classes.Util.Manager.ParametersManager");
import("Classes.Util.Parameters.DAO.ApplicationsDAO");
import("Classes.Exceptions.SecurityException");
import("Classes.Util.Security.Manager.SecurityManager");

use \PsiFramework\Classes\Util\Application;
use \PsiFramework\Classes\Util\HTTP\Request;
use \PsiFramework\Classes\Util\HTTP\Session;
use \PsiFramework\Classes\Util\Manager\ParametersManager;
use \PsiFramework\Classes\Util\Parameters\DAO\ApplicationsDAO;
use \PsiFramework\Classes\Exceptions\SecurityException;
use \PsiFramework\Classes\Util\Security\Manager\SecurityManager;

/**
 * PsiFramework
 * Php Simple Framework
 *
 * @author Rémi San
 * @version beta
 */

/**
 * The ApplicationManager class is used to manage the applications
 *
 * @package Util.UI
 */
class ApplicationManager
{

    protected static $_singleton = null;

    protected /*Application*/   $_application ;
    protected /*Session*/       $_session ;
    protected /*Request*/       $_request ;
    protected /*Application[]*/ $_applications ;

    /**
     * Constructor
     *
     * @return    ApplicationManager    instance
     */
    protected function __construct()
    {
        $this->_application = null ;
        $this->_session = Session::getInstance();
        $this->_request = Request::getInstance();

        $apps = $this->_session->get("applications");
        if (is_null($apps)) {
            $apps = ApplicationsDAO::getInstance()->getApplications();
            $this->_session->set("applications", $apps);
        }
        $this->_applications =  $apps ;

        $application = null ;
        $requestApplication = $this->_request->getParameter("application");
        if (!is_null($requestApplication)) {
            $application = $this->getApplication($requestApplication);
        } else {
            $sessionApplication = $this->_session->get("application");
            if (!is_null($sessionApplication)) {
                $application = $sessionApplication ;
            } else {
                $appParameters
                    = ParametersManager::getInstance()->
                        getApplicationsParameters();

                $hostName = $_SERVER['HTTP_HOST'] ;
                $applicationName = $appParameters->getParameter($hostName);

                $insertAppParameter = true ;
                if (isNullOrEmptyString($applicationName)) {
                    $applicationName = $appParameters->getDefaultApplication();
                } else {
                    $insertAppParameter = false ;
                }

                $application = $this->getApplication($applicationName);
                $application->insertAppParameter = $insertAppParameter ;
            }
        }
        if (is_null($application)) {
            throw new \Exception("Impossible de récupérer l'application !");
        }
        $this->setApplication($application);
    }

    public function setApplication(Application $application)
    {
        $this->_application = $application ;
        $this->_session->set("application", $application);
    }

    public function getApplicationWithSecurityCheck()
    {
        return $this->getApplication(null, true);
    }

    /**
     * 
     * @param unknown_type $applicationName
     * @param unknown_type $checkSecurity
     * @throws SecurityException
     * 
     * @return \PsiFramework\Classes\Util\Application
     */
    public function getApplication(
        /*string*/ $applicationName=null,
        /*bool*/ $checkSecurity=false
    )
    {
        if (isNullOrEmptyString($applicationName)) {
            if ($checkSecurity) {
                $securityManager = SecurityManager::getInstance();
                if ($securityManager->canReadApplication($this->_application)) {
                    return $this->_application ;
                } else {
                    throw new SecurityException(
                        "User can't access the Application !"
                    );
                }
                    
            } else {
                return $this->_application ;
            }
        } else if (isset($this->_applications[$applicationName])) {
            return $this->_applications[$applicationName] ;
        } else {
            return null ;
        }
    }

    public function getApplications()
    {
        return $this->_applications ;
    }

    /**
     * Function to be called instead of the constructor.
     *
     * @return ApplicationManager instance
     */
    public static function getInstance()
    {

        if (self::$_singleton==null) {
            self::$_singleton = new ApplicationManager();
        }

        return self::$_singleton;
    }
}
